
LHRopePoint = {}
function LHRopePoint:ropePoint()

    local object = {position = {x = 0, y = 0},
    				  oldPosition = {x = 0, y = 0}
    				  }

    setmetatable(object, { __index = LHRopePoint })  -- Inheritance        
    return object
end

function LHRopePoint:setPosition(pos)
    self.oldPosition = {x = pos.x, y = pos.y};
    self.position = {x = self.oldPosition.x, y = self.oldPosition.y};
end

function LHRopePoint:getPosition()
	return self.position;
end

function LHRopePoint:update()
    local tempPos = {x = self.position.x, y = self.position.y};
    self.position.x = self.position.x + (self.position.x - self.oldPosition.x);
    self.position.y = self.position.y + (self.position.y - self.oldPosition.y);
    self.oldPosition = {x = tempPos.x, y = tempPos.y};

end

function LHRopePoint:applyGravity(dt)

    self.b2World = LHSettings:sharedInstance().activeBox2dWorld;
    
--    if(self.b2World)then
--    	
--    		local gravX, gravY = self.b2World:getGravity();
--
--    		
--		self.position.x = self.position.x + (gravX*2.0*dt);
--		self.position.y = self.position.y + (gravY*2.0*dt);
--    else
    		self.position.y = self.position.y + (10.0*dt);
--    end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
LHRopeStick = {}
function LHRopeStick:ropeStickWithRopePointA(a, b)

	local dist = lh_Distance(a.position, b.position);

    local object = {pointA = a,
    				  pointB = b,
    				  hypotenuse = dist
    				  }

    setmetatable(object, { __index = LHRopeStick })  -- Inheritance        
    return object
end


function LHRopeStick:removeSelf()
    self.pointA = nil;
    self.pointB = nil;
end

function LHRopeStick:contract()

	local posA = self.pointA.position;
	local posB = self.pointB.position;
    
	local dx = posB.x - posA.x;
	local dy = posB.y - posA.y;
	local h  = lh_Distance(posA,posB);
	local diff = self.hypotenuse - h;
	local offx = (diff * dx / h) * 0.5;
	local offy = (diff * dy / h) * 0.5;

    self.pointA:setPosition({x = posA.x - offx, y = posA.y - offy});
    self.pointB:setPosition({x = posB.x + offx, y = posB.y + offy});
end

function LHRopeStick:ropePointA()
	return self.pointA;
end
function LHRopeStick:ropePointB()
	return self.pointB;
end

function LHRopeStick:setRopePointA(a)
    self.pointA = a;
end

function LHRopeStick:setRopePointB(b)
    self.pointB = b;
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
LHJoint = {}
function LHJoint:jointWithDictionary(jointDict, parentLoader)

    if(nil == jointDict)then
        print("ERROR: joint info dictionary is nil");
        return nil;
    end

    local object = {box2dJoint = nil,
				lhParentLoader = parentLoader,
				lhUniqueName = jointDict:stringForKey("UniqueName"),
                    lhTag = jointDict:intForKey("Tag"),
                    lhSpriteA = nil,
                    lhSpriteB = nil,
                    lhJointType = "distance"
                    }

    setmetatable(object, { __index = LHJoint })  -- Inheritance
    
            
    object:createJointFromDictionary(jointDict)
        
    if(object.box2dJoint~=nil)then
        if(object.lhSpriteA ~= nil)then
            object.lhSpriteA.lhAttachedJoint[#object.lhSpriteA.lhAttachedJoint+1] = object;
        end
    
        if(object.lhSpriteB ~= nil)then
            object.lhSpriteB.lhAttachedJoint[#object.lhSpriteB.lhAttachedJoint+1] = object;
        end
    end            
        
    return object
end
--------------------------------------------------------------------------------
function LHJoint:removeSelf()
    
    print("LHJoint removeSelf ".. self.lhUniqueName);
    
    if(self.lhParentLoader ~= nil)then
        for i = 1, #self.lhParentLoader.loadedJoints do
            if(self.lhParentLoader.loadedJoints[i] == self)then
                self.lhParentLoader.loadedJoints[i] = nil;
            end
        end
    end
        
    self.lhParentLoader = nil;
    self.lhUniqueName = nil;
    self.lhTag = nil;
    
    if(self.lhSpriteA ~= nil)then
        for i = 1, #self.lhSpriteA.lhAttachedJoint do
            if(self.lhSpriteA.lhAttachedJoint[i] == self)then
                self.lhSpriteA.lhAttachedJoint[i] = nil
            end
        end
    end

    if(self.lhSpriteB ~= nil)then
        for i = 1, #self.lhSpriteB.lhAttachedJoint do
            if(self.lhSpriteB.lhAttachedJoint[i] == self)then
                self.lhSpriteB.lhAttachedJoint[i] = nil
            end
        end
    end
    
    
    self.lhSpriteA = nil;
    self.lhSpriteB = nil;
    self.lhJointType = nil;
    
     self.b2World:destroyJoint(self.box2dJoint);
    self.box2dJoint = nil
    self.b2World = nil;
    self = nil
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function LHJoint:prepareRopeJointsWithDictionary(dictionary)

    self.rope_showRepresentation = false;
    self.rope_textureName = "";
    self.rope_z = 0;
    
    if(dictionary:boolForKey("ShowRepresentation"))then
    
        if(dictionary:objectForKey("RepresentationZ"))then
            self.rope_z = dictionary:intForKey("RepresentationZ");
        end
        self.rope_showRepresentation = true;
        if(dictionary:objectForKey("TextureName"))then
        
            local textureName = dictionary:stringForKey("TextureName");
            
            self.rope_textureName = texture;
            
            if(dictionary:objectForKey("SegmentsFactor"))then
                self.rope_segmentFactor = dictionary:intForKey("SegmentsFactor");
            else
                self.rope_segmentFactor = 12.0;
            end
                        
                        
            self.rope_spriteSheet = Texture.new(textureName, true, {wrap = Texture.REPEAT}) -- enable filtering and repeat the texture
			
			
           if(self.rope_spriteSheet)then
                        
                    self.rope_points = {};
                    self.rope_sticks = {};
                    self.rope_sprites = {};
                    
                    self:createRopeJointRepresentation();
                    --self:scheduleUpdate();
                    
                    stage:addEventListener(Event.ENTER_FRAME, self.enterFrame, self)
                    
            end
        else
            print("Rope texture " .. self.lhUniqueName .. " does not have a texture but want's visual representation");
        end
    end
end




function LHJoint:updateRopePointsWithA(pointA, pointB, dt)

	if(#self.rope_points > 1)then
	
		local rpPointA = self.rope_points[1];
		local rpPointB = self.rope_points[#self.rope_points];
		
		rpPointA:setPosition(pointA);
		rpPointB:setPosition(pointB);

		for i=1, self.rope_numPoints-1 do
			
			local rpA = self.rope_points[i];
			
			rpA:applyGravity(dt);
			rpA:update();
			
		end

		for j=1, 5 do
		
			for i = 1, self.rope_numPoints-1 do
			
				local rpStick = self.rope_sticks[i];
				rpStick:contract();
			end
		
		end
    end
end

function LHJoint:updateRopeSprites()

	if(self.rope_spriteSheet)then
    
    		for i = 1, self.rope_numPoints-1 do
    		
    			local rpStick = self.rope_sticks[i];
    		
    			local pointA = rpStick.pointA;
    			local pointB = rpStick.pointB;
    		
    			local stickAngle = lh_ToAngle(lh_Sub(pointA.position, pointB.position));
    			
    			local tmpSprite = self.rope_sprites[i];
    			local sprPos = lh_Midpoint(pointA.position, pointB.position);
    			tmpSprite:setPosition(sprPos.x, sprPos.y);			
    			tmpSprite:setRotation(LH_RADIANS_TO_DEGREES(stickAngle));
		end
	end
end






function LHJoint:enterFrame(event)
	
	if(self.lhJointType == "rope")then
		local pointAx, pointAy = self.box2dJoint:getAnchorA();
		local pointBx, pointBy = self.box2dJoint:getAnchorB();
						
		self:updateRopePointsWithA({x = pointAx, y = pointAy}, {x = pointBx, y = pointBy}, event.deltaTime);		
		self:updateRopeSprites();
	end
end


function LHJoint:createRopeJointRepresentation()

    	local pointAx, pointAy  = self.box2dJoint:getAnchorA();
    	
    	local pointA = {x = pointAx, y = pointAy};
    	
    	local pointBx, pointBy  = self.box2dJoint:getAnchorB();
    	local pointB = {x = pointBx, y = pointBy};
    	
    	local length    =  self.box2dJoint:getMaxLength();

    	self.rope_points = nil;
    	self.rope_points = {};
    	
    	self.rope_sticks = nil;
   	self.rope_sticks = {};

	for i=1, #self.rope_sprites do
		local spr = self.rope_sprites[i];
		spr:removeFromParent();
	end
 
 	self.rope_sprites = nil;
    	self.rope_sprites = {};
    	self.rope_numPoints = length/self.rope_segmentFactor;
    
	local diffVector = lh_Sub(pointB,pointA);
	local multiplier = length / (self.rope_numPoints-1);
    
	local antiSagHack = 0.1; --HACK: scale down rope points to cheat sag. set to 0 to disable, max suggested value 0.1
	
	for i =1, self.rope_numPoints do
	
		local tmpPos = lh_Add(pointA, lh_Mult(lh_Normalize(diffVector),multiplier*i*(1-antiSagHack)));

	 	rpPoint = LHRopePoint:ropePoint();
		rpPoint:setPosition(tmpPos);
		self.rope_points[#self.rope_points+1] = rpPoint;--lh_deepcopy(rpPoint);
	end
	
	for i =1, self.rope_numPoints-1 do
		
		local ptA = self.rope_points[i];
		local ptB = self.rope_points[i+1];
		
	 	stick = LHRopeStick:ropeStickWithRopePointA(	 ptA, 
											 	 ptB);
		
		self.rope_sticks[#self.rope_sticks+1] = stick;--lh_deepcopy(stick);
	end
		
    if(self.rope_spriteSheet)then
    
		for i = 1, self.rope_numPoints-1 do
		
			local stickObj = self.rope_sticks[i];
			
			local pointA = stickObj.pointA;
			local pointB = stickObj.pointB;
		
		
			local stickVector = lh_Sub(pointA.position, pointB.position);
			local stickAngle = lh_ToAngle(stickVector);
			
			local region = TextureRegion.new(self.rope_spriteSheet, 0,   0,   multiplier, self.rope_spriteSheet:getHeight());
			local tmpSprite  = Bitmap.new(region )
			
			local sprPos = lh_Midpoint(pointA.position, pointB.position);
			
			tmpSprite:setPosition(sprPos.x, sprPos.y);
			tmpSprite:setRotation(LH_RADIANS_TO_DEGREES(stickAngle));
			
            if(self.rope_z < 1)then
                self.rope_z = 1;
            end
                
            if(self.lhSpriteA ~= nil and self.lhSpriteA:getParent() ~= nil)then
            
                if(self.rope_z > self.lhSpriteA:getParent():getNumChildren())then
                    self.rope_z =self.lhSpriteA:getParent():getNumChildren() 
                end
                
                self.lhSpriteA:getParent():addChildAt(tmpSprite,self.rope_z);
            else
                stage:addChild(tmpSprite);
            end
	        self.rope_sprites[#self.rope_sprites+1] = tmpSprite;
        
		
		end
	end
end


function LHJoint:ropeWasCut()

end


function LHJoint:createTipBody()
	
	local world = self.b2World;
	if(world)then
	
		local bodyDef = {};	
		bodyDef.type = b2.DYNAMIC_BODY;
		
		bodyDef.position = {x = 0, y = 0};
		 		
		local body = world:createBody(bodyDef);	

		local circleShape = b2.CircleShape.new(0, 0, 1.0);

		local fixDef = {}
		fixDef.shape = circleShape;
		fixDef.density = 10.0;
		fixDef.filter = { maskBits = 0};
											
		local fix = body:createFixture(fixDef);
												
		return body;
    end
    
    return nil;
end




function LHJoint:cutRopeAtStick(stick, newBodyA, newBodyB)

    -- Find out where the rope will be cut
    local nPoint = lh_indexOfObjectInTable(self.rope_sticks, stick);
    
    if(nPoint == 0)then
	    return false;
    end
    
    -- Position the new dummy bodies
    local pointOfBreak = self.rope_points[nPoint];
    
    
    local newBodiesPosition = pointOfBreak.position;
    newBodyA:setPosition(newBodiesPosition.x, newBodiesPosition.y);
    newBodyB:setPosition(newBodiesPosition.x, newBodiesPosition.y);

    -- Get a reference to the world to create the new joint
    local world = self.b2World;
    
    -- This will determine how long the rope is now and how long the new rope will be
	local cutRatio = nPoint / (self.rope_numPoints);

    -- Re-create the joint    
    
    local x,y = newBodyA:getPosition()
    print(x, y);
    
    local rj = b2.createRopeJointDef(	self.box2dJoint:getBodyA(),
								    	newBodyB, 
								    	self.rope_localAnchorA.x, self.rope_localAnchorA.y,
								    	newBodiesPosition.x, newBodiesPosition.y,
								    	self.box2dJoint:getMaxLength()*cutRatio);
         
    
    -- Create the new rope joint
    local rj2 = b2.createRopeJointDef(newBodyA,
								  self.box2dJoint:getBodyB(),
								  newBodiesPosition.x, newBodiesPosition.y,
								  self.rope_localAnchorB.x, self.rope_localAnchorB.y,
								  self.box2dJoint:getMaxLength()*(1 - cutRatio));

	newJoint1 = self.b2World:createJoint(rj)
	newJoint2 = self.b2World:createJoint(rj2)
								  
								  
								  
								  
	-- Destroy the old joint and update to the new one
   	world:destroyJoint(self.box2dJoint);
	self.box2dJoint = newJoint1;
    self.lhJointType = "rope";        
    
   
   
   
   	self.rope_points = nil;
	self.rope_points = {};
    	
	self.rope_sticks = nil;
   	self.rope_sticks = {};

	for i=1, #self.rope_sprites do
		local spr = self.rope_sprites[i];
		spr:removeFromParent();
	end
	self.rope_sprites = nil;
	self.rope_sprites = {};
	self.rope_numPoints = 0;

--    
--    rope_wasCut = true;
--#ifndef LH_ARC_ENABLED
--    joint->SetUserData(self);
--#else
--    joint->SetUserData((__bridge void*)self);
--#endif
--
--    
--    
--    NSMutableDictionary* dictionary = [NSMutableDictionary dictionary];
--    [dictionary setObject:[NSNumber numberWithBool:rope_showRepresentation]
--                   forKey:@"ShowRepresentation"];
--    if(rope_textureName){
--        [dictionary setObject:rope_textureName
--                       forKey:@"TextureName"];
--    }
--    [dictionary setObject:[NSString stringWithFormat:@"%@1", uniqueName]
--                   forKey:@"UniqueName"];
--    
--    [dictionary setObject:[NSNumber numberWithInt:rope_segmentFactor]
--                   forKey:@"SegmentsFactor"];
--    
--    [dictionary setObject:[NSNumber numberWithInt:rope_z]
--                   forKey:@"RepresentationZ"];
--    
--    
--    LHJoint* newLhJoint = [LHJoint ropeJointWithDictionary:dictionary
--                                                     joint:newJoint2
--                                                    loader:parentLoader];
--    if(newLhJoint){
--        [newLhJoint setTag:tag];
--        [parentLoader addJoint:newLhJoint];
--    }
--
--    
--    
--    
	self:createRopeJointRepresentation();
--    
--    
--    
    return true;
    
end




function LHJoint:cutRopeJointIntesectedWithLineFromPointsAtoB(ptA, ptB)


	if(self.lhJointType ~= "rope")then 
		return false 
	end
	
    for i=1, #self.rope_sticks do
    
	    	local stick = self.rope_sticks[i];
    		local pa = stick.pointA.position;
    		local pb = stick.pointB.position;
    		
    		if(true == lh_checkLineIntersection(ptA, ptB, pa, pb))then
    		
    			local newBodyA = self:createTipBody();
            	local newBodyB = self:createTipBody();
            
            	self:cutRopeAtStick(stick, newBodyA, newBodyB);
            
            	return true;
    		end
    end
    
    return false;
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function LHJoint:createJointFromDictionary(jointInfo)

    self.b2World = LHSettings:sharedInstance().activeBox2dWorld 
    

    if(nil == self.b2World)then
        return nil;
    end    
    
    if(nil == self.lhParentLoader)then
        return nil;
    end

    local objA = self.lhParentLoader:spriteWithUniqueName(jointInfo:stringForKey("ObjectA"));
    local objB = self.lhParentLoader:spriteWithUniqueName(jointInfo:stringForKey("ObjectB"));
    
    if objA == nil or objB == nil then
        return nil
    end
        
    if objA == objB then
        print("ERROR: ObjectA equal ObjectB in joint creation - Box2D will assert.")
        return nil
    end
    
    self.lhSpriteA = objA;
    self.lhSpriteB = objB;
    
    local anchorA = jointInfo:pointForKey("AnchorA");
    local anchorB = jointInfo:pointForKey("AnchorB");
    
    anchorA.x = anchorA.x*objA.lhScaleWidth;
    anchorA.y = anchorA.y*objA.lhScaleHeight;
        
    anchorB.x = anchorB.x*objB.lhScaleWidth;
    anchorB.y = anchorB.y*objB.lhScaleHeight;
    
    if true == jointInfo:boolForKey("CenterOfMass") then
        anchorA.x = 0
        anchorB.x = 0
        anchorA.y = 0
        anchorB.y = 0
    end
    
    if jointInfo:intForKey("Type") == 0 then -- distance joint    

        local dj = b2.createDistanceJointDef(objA.body, objB.body, 
                                                objA:getX() +anchorA.x, objA:getY() +anchorA.y,
                                                objB:getX() +anchorB.x, objB:getY() +anchorB.y);
         
        self.box2dJoint = self.b2World:createJoint(dj)

        self.box2dJoint:setFrequency(jointInfo:floatForKey("Frequency"));
        self.box2dJoint:setDampingRatio(jointInfo:floatForKey("Damping"));
        self.lhJointType = "distance";
        
    elseif jointInfo:intForKey("Type") == 1 then -- revolute joint

        local rj = b2.createRevoluteJointDef(objA.body, objB.body, 
                                                   objA:getX() +anchorA.x, objA:getY() +anchorA.y);
        self.box2dJoint = self.b2World:createJoint(rj)
        
        self.box2dJoint:enableLimit(jointInfo:boolForKey("EnableLimit"));
        
        local lowerAngle = jointInfo:floatForKey("LowerAngle");
        local upperAngle = jointInfo:floatForKey("UpperAngle");
        if(lowerAngle < upperAngle)then
	        self.box2dJoint:setLimits(jointInfo:floatForKey("LowerAngle")*(math.pi/180), jointInfo:floatForKey("UpperAngle")*(math.pi/180));
         elseif(lowerAngle ~= 0 and upperAngle ~= 0)then
             print("Revolute joint " .. self.lhUniqueName .. " lower angle is bigger then upper angle");
         end
        
        self.box2dJoint:enableMotor(jointInfo:boolForKey("EnableMotor"));
        self.box2dJoint:setMotorSpeed(jointInfo:floatForKey("MotorSpeed"));
        self.box2dJoint:setMaxMotorTorque(jointInfo:floatForKey("MaxTorque"));        
        self.lhJointType = "revolute";

    elseif jointInfo:intForKey("Type") == 2 then -- prismatic joint

        local axis = jointInfo:pointForKey("Axis");
        local pj = b2.createPrismaticJointDef(objA.body, objB.body, 
                                                   objA:getX() +anchorA.x, objA:getY() +anchorA.y,
                                                   axis.x,axis.y );
        self.box2dJoint = self.b2World:createJoint(pj)
        
        self.box2dJoint:enableLimit(jointInfo:boolForKey("EnableLimit"));
        
        local lowerLimit = jointInfo:floatForKey("LowerTranslation")/2;
        local upperLimit = jointInfo:floatForKey("UpperTranslation")/2;
        
        if(lowerLimit < upperLimit)then
            self.box2dJoint:setLimits(lowerLimit,upperLimit)
        elseif (lowerLimit ~= 0 and upperLimit ~= 0)then
            print("Prismatic joint " .. self.lhUniqueName .. " lower limit is bigger then upper limit");
        end
        
        self.box2dJoint:enableMotor(jointInfo:boolForKey("EnableMotor"));
        self.box2dJoint:setMotorSpeed(jointInfo:floatForKey("MotorSpeed"));
        self.box2dJoint:setMaxMotorForce(jointInfo:floatForKey("MaxMotorForce"));

        self.lhJointType = "prismatic";

    elseif jointInfo:intForKey("Type") == 3 then -- pulley joint
    
        local groundAnchorA = jointInfo:pointForKey("GroundAnchorRelativeA");
        local groundAnchorB = jointInfo:pointForKey("GroundAnchorRelativeB");
    
    
        local pj = b2.createPulleyJointDef(objA.body, objB.body, 
                                               objA:getX() + groundAnchorA.x, objA:getY() + groundAnchorA.y, 
                                         objB:getX() + groundAnchorB.x, objB:getY() + groundAnchorB.y, 
                                         objA:getX() + anchorA.x,objA:getY() + anchorA.y, 
                                         objB:getX() + anchorB.x,objB:getY() + anchorB.y, 
                                         jointInfo:floatForKey("Ratio") );
        self.box2dJoint = self.b2World:createJoint(pj)
        self.lhJointType = "pulley";
        
    elseif jointInfo:intForKey("Type") == 4 then -- gear joint                                        
        
        
        local lhJointA = self.lhParentLoader:jointWithUniqueName(jointInfo:stringForKey("JointA"));
        local b2JointA = lhJointA.box2dJoint;
        
        local lhJointB = self.lhParentLoader:jointWithUniqueName(jointInfo:stringForKey("JointB"));
        local b2JointB = lhJointB.box2dJoint;

                        
         if(b2JointA == nil or b2JointB == nil)then
            return;
         end
            
        local gj = b2.createGearJointDef(objA.body, objB.body,
                                              b2JointA, b2JointB,
                                         jointInfo:floatForKey("Ratio") );
        self.box2dJoint = self.b2World:createJoint(gj)                                 
            self.lhJointType = "gear";
           
        
    elseif jointInfo:intForKey("Type") == 5 then -- wheel joint

        local axis = jointInfo:pointForKey("Axis");
        
        local wj = b2.createWheelJointDef(objA.body, objB.body,
                                                  objA:getX() +anchorA.x, objA:getY() +anchorA.y, 
                                            axis.x, axis.y);
                                    
        self.box2dJoint = self.b2World:createJoint(wj)  
        
        self.box2dJoint:enableMotor(jointInfo:boolForKey("EnableMotor"));
        self.box2dJoint:setMotorSpeed(jointInfo:floatForKey("MotorSpeed"));
        self.box2dJoint:setMaxMotorTorque(jointInfo:floatForKey("MaxTorque"));
        self.box2dJoint:setSpringFrequencyHz(jointInfo:floatForKey("Frequency"));
        self.box2dJoint:setSpringDampingRatio(jointInfo:floatForKey("Damping"));
        
        self.lhJointType = "wheel";
        
    elseif jointInfo:intForKey("Type") == 6 then -- weld joint

         local wj = b2.createWeldJointDef(objA.body, objB.body,
                                                  objA:getX() +anchorA.x, objA:getY() +anchorA.y);                                    
        self.box2dJoint = self.b2World:createJoint(wj)  
        self.lhJointType = "weld";

    elseif jointInfo:intForKey("Type") == 7 then -- rope joint
    
        local bend = jointInfo:floatForKey("MaxLength");
                
       if(bend <= 0)then
            bend = 0.01;
        end
                
       local dx = objA:getX() - objB:getX();
        local dy = objA:getY() - objB:getY();
 
          local length = math.sqrt(dx * dx + dy * dy);

       local maxLength = length  * bend;
       self.rope_localAnchorA = {x=  objA:getX() +anchorA.x,y = objA:getY() +anchorA.y};
       self.rope_localAnchorB = {x=  objB:getX() +anchorB.x,y = objB:getY() +anchorB.y};
       self.rope_length = maxLength;
       
       local rj = b2.createRopeJointDef(objA.body, objB.body, 
                                                objA:getX() +anchorA.x, objA:getY() +anchorA.y,
                                                objB:getX() +anchorB.x, objB:getY() +anchorB.y,
                                                maxLength);
         
        self.box2dJoint = self.b2World:createJoint(rj)
        self.lhJointType = "rope";        

        self:prepareRopeJointsWithDictionary(jointInfo);
                
    elseif jointInfo:intForKey("Type") == 8 then -- friction joint
    
         local fj = b2.createFrictionJointDef(objA.body, objB.body,
                                                    objA:getX() +anchorA.x, objA:getY() +anchorA.y);                                    
        self.box2dJoint = self.b2World:createJoint(fj)  
    
         self.box2dJoint:setMaxForce(jointInfo:floatForKey("MaxForce"));
         self.box2dJoint:setMaxTorque(jointInfo:floatForKey("MaxTorque"));
        
        self.lhJointType = "friction";        
    else
        print("Unknown joint type " .. jointInfo:intForKey("Type") .." in LevelHelper file.")
    end 
end